package com.wyw.learning.thread.threadlocal;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用ThreadLocal解决加锁效率低的问题
 *  每个线程有自己的SimpleDateFormat对象
 *
 * ThreadLocal的两大使用场景
 *  典型场景1：每个线程需要一个独享的对象（通常是工具类，典型需要使用的类有SimpleDateFormat和Random）
 *      主要强调的是每个线程内都有自己实例副本，不共享
 *      这里解释一下Random，本身Random就是获取一个随机数，从随机角度考虑，不同的线程是没有影响的
 *      这里Random使用ThreadLocal，主要是为了解决效率问题，如果多线程都需要等待一个共享的随机数生成器java.util.Random类，这样做是很低效的
 *      可以使用TgreadLocal辅助类为各个线程提供一个单独的生成器，不过Java SE7还提供了一种便利类
 *          int random = ThreadLocalRandom.current().nextInt(upperBound);
 *          ThreadLocalRandom.current()调用返回特定于当前线程的Random类实例
 *  典型场景2：每个线程内需要保存全局变量（例如在拦截器中获取用户信息），可以让不同方法直接使用，避免参数传递的麻烦
 *
 * @author Mr Wu    yewen.wu.china@gmail.com
 * @date 2021/7/6   10:40 下午
 * <p>
 * Update History:
 * Author        Time            Content
 */
public class ThreadLocalNormalUsage05 {
    public static ExecutorService threadpool = Executors.newFixedThreadPool(10);
    public static void main(String[] args) {
        for(int i =0; i < 1000; i ++){
            int finalI = i;

            threadpool.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(new ThreadLocalNormalUsage00().date(finalI));
                }
            });
        }
        threadpool.shutdown();
    }

    public String date(int seconds){
        Date date = new Date(1000 * seconds);
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf = ThreadSafeFormatter.dateFormatThreadLocal.get();
        return sdf.format(date);
    }
}

class ThreadSafeFormatter {
//    public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal =
//            new ThreadLocal<SimpleDateFormat>(){
//                @Override
//                protected SimpleDateFormat initialValue() {
//                    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                }
//            };

    //lambda表达式
    public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal
            = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

}
